package com.medicine.common.utils;

import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.PeriodType;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateUtils {
    /**
     * 获取日期开始时间
     * @param date
     * @return
     */
    public static Date getEndOfDay(Date date) {
        if (date == null){
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取日期结束时间
     * @param date
     * @return
     */
    public static Date getStartOfDay(Date date) {
        if (date==null){
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取日期月份第一天
     * @param date
     * @return
     */
    public static Date getStartDayOMonth(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        localDateTime = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取日期月份最后一天
     * @param date
     * @return
     */
    public static Date getEndDayOfMonth(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        localDateTime = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取月份最后一天的零点前时间
     * @param date
     * @return
     */
    public static Date getEndTimeOfMonth(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        localDateTime = localDateTime.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static String getYyyyMMddHHmmss() {
        Date currentDate = new Date();
        String dateStr4yyyyMMddHHmmss = new SimpleDateFormat("yyyyMMddHHmmss").format(currentDate);
        return dateStr4yyyyMMddHHmmss;
    }

    public static String getYyyyMMddHHmmss(Date date) {
        if (date == null){
            return null;
        }
        String dateStr4yyyyMMddHHmmss = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        return dateStr4yyyyMMddHHmmss;
    }

    public static String getYyyyMMdd() {
        Date currentDate = new Date();
        String dateStr4yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(currentDate);
        return dateStr4yyyyMMdd;
    }

    public static String getYYYYMMDD(Date date) {
        if (date == null) {

            return "";
        }

        String dateStr4yyyyMMdd = new SimpleDateFormat("yyyy-MM-dd").format(date);
        return dateStr4yyyyMMdd;
    }

    public static String getDateStringByPattern(Date date,String pattern) {
        if (date == null) {

            return "";
        }

        String dateStr = new SimpleDateFormat(pattern).format(date);
        return dateStr;
    }

    public static String getYmdWithoutSplit(Date date) {
        if (date == null) {

            return "";
        }

        String dateStr4yyyyMMdd = new SimpleDateFormat("yyyyMMdd").format(date);
        return dateStr4yyyyMMdd;
    }

    public static int getAgeByBirthday(Date birthday) {
        if (birthday == null) {
            return 0;
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(birthday.getTime()), ZoneId.systemDefault());
        Long age = ChronoUnit.YEARS.between(localDateTime, LocalDateTime.now());
        return age.intValue();
    }

    public static Date getValidTime(int timeunit) {
        DateTime dateTime = new DateTime();
        dateTime = dateTime.plusMinutes(timeunit);
        return dateTime.toDate();
    }

    public static String splitYYYYmmDD(String str) throws ParseException {
        Date date= new SimpleDateFormat("yyyy-MM-dd").parse(str);
        String newStr = new SimpleDateFormat("yyyy-MM").format(date);
        return newStr;
    }

    public static Date stringToDate(String str) throws ParseException {
        DateFormat format= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date=format.parse(str);
        return date;
    }

    public static Date stringToYMDDate(String str) throws ParseException {
        DateFormat format= new SimpleDateFormat("yyyy-MM-dd");
        Date date=format.parse(str);
        return date;
    }

    public static Date stringToDateByPattern(String str,String pattern) throws ParseException {
        if (StringUtils.isEmpty(str)){
            return null;
        }
        DateFormat format= new SimpleDateFormat(pattern);
        Date date=format.parse(str);
        return date;
    }


    public static Date nextDays(Date date, int nextDays) {
        GregorianCalendar c1 = new GregorianCalendar();
        c1.setTime(date);
        GregorianCalendar cloneCalendar = (GregorianCalendar) c1.clone();
        cloneCalendar.add(Calendar.DATE, nextDays);
        return cloneCalendar.getTime();
    }

    public static Date nextMonths(Date date, int nextMonth) {
        GregorianCalendar c1 = new GregorianCalendar();
        c1.setTime(date);
        GregorianCalendar cloneCalendar = (GregorianCalendar) c1.clone();
        cloneCalendar.add(Calendar.MONTH, nextMonth);
        return cloneCalendar.getTime();
    }

    public static int timeMinus(String before, String after) throws ParseException {
        DateTime beforeTime = new DateTime(stringToYMDDate(before));
        DateTime afterTime = new DateTime(stringToYMDDate(after));

        Period period = new Period(beforeTime, afterTime, PeriodType.days());
        return period.getDays();
    }

    /**
     *
     * @param nowTime   当前时间
     * @param startTime	开始时间
     * @param endTime   结束时间
     * @return
     * @author sunran   判断当前时间在时间区间内
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     *  获取当前日期是星期几<br>
     *  周一MON 周二TUE 周三WED 周四THU 周五FRI 周六STA 周日SUN
     *  @param dt
     *  @return 当前日期是星期几
     */
    public static String getWeekOfDate(Date dt) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return weekDays[w];
    }
}
